﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LightCAD.Model
{

    public class Cone3dAction : Solid3dAction
    {
        private LcCone cone = null;
        private Vector3 Center;
        private Vector3 Normal;
        public Cone3dAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：Cone");
        }
        public async void ExecCreate(string[] args = null)
        {
            Vector3 startP = null;
            Vector3 endP = null;
            //PointInputer3d pointer = new PointInputer3d(docEditor);
            FaceInputerResult pr = null;
            PlanarSurface3d plane = null;
            //LcSolid3d solidEle = null;
            double pullDist = 0;
            bool startPush = false;
            StartAction();
            this.model3dRuntime.EnableCameraControl(false);
            void onMouseEvent(string name, MouseEventRuntime mer)
            {
                if (name == "Move")
                {
                    if (!startPush)
                    {
                        if (startP == null)
                        {
                            return;
                        }

                        endP = this.snap3dRuntime.SnapPoint.Clone();
                        if (endP != null)
                        {
                            this.CreateOrUpdateCuboid(startP, endP, 1);
                        }
                    }
                    else
                    {
                        Move(this.snap3dRuntime.SnapPoint);
                    }
                }
                else if (name == "Down")
                {
                    if (startP == null)
                    {
                        startP = this.snap3dRuntime.SnapPoint.Clone();
                    }
                    else if (!startPush)
                    {
                        startPush = true;
                        //var topFace = this.cuboid.Solid.TopoFaceModel.Surfaces[4];
                        //pr = new FaceInputerResult()
                        //{
                        //    Surface = topFace,
                        //    Element = this.cuboid,
                        //    SnapPoint = this.snap3dRuntime.SnapPoint.Clone()
                        //};

                        //plane = pr.Surface as PlanarSurface3d;
                        //solidEle = pr.Element as LcSolid3d;
                        this.snap3dRuntime.ClearSnapPlanes();
                        var camera = this.snap3dRuntime.GetCamera();
                        var xAxis = (endP - startP).Normalize();
                        var yAxis = Vector3.ZAxis;
                        var zAxis = xAxis.Clone().Cross(yAxis).Normalize();
                        this.snap3dRuntime.AddSnapPlanes(new ListEx<Plane>
                        {
                            new Plane().SetFromNormalAndCoplanarPoint(zAxis, startP.Clone())
                        });
                    }
                    else if (startPush)
                    {
                        this.snap3dRuntime.EndSnaping();
                        this.model3dRuntime.Control.DetachEvents(null, null, onMouseEvent, null, null, null, null);
                        this.snap3dRuntime.ClearSnapPlanes();
                        this.model3dRuntime.EnableCameraControl(true);
                    }
                }
            }

            void Move(Vector3 target)
            {
                //var pullTotal = (target - pr.SnapPoint).Dot(plane.Normal);
                //var offset = pullTotal - pullDist;
                //pullDist = pullTotal;
                CreateOrUpdateCuboid(startP, endP, target.Z);
                //solidEle.PushOrPullFace(plane, offset);
            }
        Step0: //选择工作平面
            var planeInputer = new SurfaceInputer3d(this.docEditor);
            var result = await planeInputer.Execute("选中一个面");
            if (result?.IsCancelled ?? true)
                goto cancel;
            pr = result.ValueX as FaceInputerResult;
            if (pr.Surface is PlanarSurface3d)
                goto Step1;
            else
                goto Step0;

        Step1: //绘制工作平面
            var center = pr.SnapPoint.Clone();
            var interSect = pr.Intersection;
            var mesh = pr.Intersection.target as Mesh;
            mesh.geometry.computeBoundingBox();
            var normal = interSect.face.normal;
            var box = mesh.geometry.boundingBox;
            this.model3dRuntime.CameraControl.Focus(center, normal.Clone(), box);

            var width = box.Max.DistanceTo(box.Min) * 10;
            var planeGeo = new PlaneGeometry(width, width);
            var planeMat = new MeshPhongMaterial()
            {
                color = new Color(0xffffff),
                transparent = true,
                opacity = 0.5,
                polygonOffset = true,
                polygonOffsetUnits = -1,
                polygonOffsetFactor = -1
            };
            var planeMesh = new Mesh(planeGeo, planeMat);
            planeMesh.layers.set(Doc3dEditRuntime.UnSelectChannel);
            planeMesh.lookAt(normal.X, normal.Y, normal.Z);
            planeMesh.position = center;

            this.Center = center.Clone();
            this.Normal = normal.Clone();

            this.snap3dRuntime.SnapGroup.add(planeMesh);
            this.snap3dRuntime.AddSnapPlanes(new ListEx<Plane>
            {
                new Plane().SetFromNormalAndCoplanarPoint(normal, center)
            });

            this.snap3dRuntime.StartSnaping(SnapFilterType.OnlyPlane);
            this.model3dRuntime.Control.AttachEvents(null, null, onMouseEvent, null, null, null, null);

        cancel:
        end:
            EndAction();
        }

        public void CreateOrUpdateCuboid(Vector3 start, Vector3 end, double height)
        {
            if (this.cone != null)
            {
                this.docRt.Document.ModelSpace.RemoveElement(this.cone);
            }

            var mats = new LcMaterial[2]
            {
                new LcMaterial() { Color = new Color(0xff0000) },
                new LcMaterial() { Color = new Color(0x00ff00) }
            };
            
            double radius = end.DistanceTo(start);

            this.cone = new LcCone(radius, 1000, mats);
            this.cone.Solid.Topoable = true;
            this.cone.Initilize(this.docRt.Document);
            this.cone.Rt3DAction = this;
            var quat = new Quaternion().SetFromUnitVectors(new Vector3(0, 0, 1), this.Normal);
            this.cone.Euler.SetFromQuaternion(quat, Euler.RotationOrders.XYZ);
            this.cone.Position.Add(start);
            this.cone.UpdateMatrix();
            this.docRt.Document.ModelSpace.InsertElement(this.cone);
        }
    }
}
